package com.bluedot.www.core.service;


import com.bluedot.www.core.common.HandwritingRuntimeException;
import com.bluedot.www.core.common.ResultCodeEnum;
import com.bluedot.www.core.dao.Execute;
import com.bluedot.www.core.pojo.BO.MailBo;
import com.bluedot.www.core.pojo.DO.Audit;
import com.bluedot.www.core.pojo.DO.Group;
import com.bluedot.www.core.pojo.DO.User;
import com.bluedot.www.core.pojo.VO.ViewAuditInfo;
import com.bluedot.www.core.utils.DbUtil;
import com.bluedot.www.core.utils.MailUtil;
import com.bluedot.www.core.utils.OSSManageUtil;
import com.bluedot.www.framework.mvc.servlet.http.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 审核表，审核心理咨询师 服务类
 * </p>
 *
 * @author zhouxuan
 * @since 2021-08-07
 */
public class AuditService {

    private static final String AUDIT_MAPPER_ADDRESS = "com.bluedot.www.core.mapper.xml.AuditMapper.";

    public static Object execute(String methodName, Object[] param) {
        AuditService auditService = new AuditService();
        Object result = null;
        switch (methodName) {
            case "deleteAuditByAuditId":
                result = auditService.deleteAuditByAuditId((List<Long>) param[0]);
                break;
            case "findAuditByAuditId":
                result = auditService.findAuditByAuditId((Long) param[0]);
                break;
            case "findAuditByUserId":
                result = auditService.findAuditByUserId((Long) param[0]);
                break;
            case "findAuditByAuditIdView":
                result = auditService.findAuditByAuditIdView((Long) param[0]);
                break;
            case "doAudit":
                result = auditService.doAudit((Long) param[0], (Long) param[1], (Long) param[2], (Long) param[3], (String) param[4]);
                break;
            case "addAudit":
                result = auditService.addAudit((Audit) param[0]);
                break;
            case "uploadImg":
                result = auditService.uploadImg((MultipartFile) param[0]);
                break;
            case "countAudit":
                result = auditService.countAudit();
                break;
            default:
                throw new RuntimeException("Method NOT FOUND, method name: " + methodName);
        }
        return result;
    }

    /**
     * 根据申请id删除申请
     *
     * @param auditIds 申请id
     * @return Boolean
     * @author Ding YuXing
     * @date 2021/8/8 10:45
     */
    private Boolean deleteAuditByAuditId(List<Long> auditIds) {
        List<Long> lastAuditIds = new ArrayList<>();
        for (Long auditId : auditIds) {
            Integer auditResult = findAuditResultByAuditId(auditId);
            //不能删除未审核的记录
            if (auditResult != 0) {
                lastAuditIds.add(auditId);
            }
        }

        //如果全是未审核的记录那么直接返回false
        if (lastAuditIds.size() == 0) {
            return false;
        }

        int i = 0;
        for (Long lastAuditId : lastAuditIds) {
            Integer result = (Integer) Execute.execute(Execute.UPDATE_TYPE, AUDIT_MAPPER_ADDRESS + "deleteAuditByAuditId", new Object[]{lastAuditId});
            if (result == 1) {
                i++;
            }
        }
        return i == lastAuditIds.size();
    }

    /**
     * 通过申请id查看申请结果
     *
     * @param auditId 申请id
     * @return Integer
     * @author Ding YuXing
     * @date 2021/8/8 10:45
     */
    private Integer findAuditResultByAuditId(Long auditId) {
        List<Audit> audits = (List<Audit>) Execute.execute(Execute.QUERY_TYPE, AUDIT_MAPPER_ADDRESS + "findAuditResultByAuditId", new Object[]{auditId});
        return audits.get(0).getAuditResult();
    }

    /**
     * 上传文件至阿里云
     *
     * @param multipartFile:
     * @return java.lang.String 文件连接
     * @author He Peng
     * @date 2021/9/20 19:51
     */
    public String uploadImg(MultipartFile multipartFile) {
        String filename = multipartFile.getOriginalFilename();
        String filetype = filename.substring(filename.lastIndexOf(".") + 1);
        if (!"jpg".equals(filetype) && !"png".equals(filetype)) {
            throw new HandwritingRuntimeException(ResultCodeEnum.PARAM_ERROR);
        }
        String url = null;
        try {
            InputStream in = multipartFile.getInputStream();
            url = OSSManageUtil.uploadFile(in, multipartFile.getOriginalFilename(), "bluedot/photo/");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return OSSManageUtil.getAccessUrl() + url;
    }


    /**
     * 增加申请
     *
     * @param audit 申请对象
     * @return Boolean
     * @author Ding YuXing
     * @date 2021/8/8 10:45
     */
    private Boolean addAudit(Audit audit) {
        //传到这里的申请对象还少了几个参数
//        包含的参数有
        //用户id 性别gender 心理咨询师证件图片链接certificate_img
        //身份证正面照id_card_img 证件等级certificate_level 从业时间working_time
        //用户真实姓名name 身份证号id_card_num 出生年月birthday 从事本职业工作时间working_year
        //申请描述apply_des
//        要增加
        //主键id，gmt_create创建时间，gmt_modified修改时
        Long id = DbUtil.generateId();
        audit.setId(id);

        //创建时间
        Timestamp gmtCreateTime = new Timestamp(System.currentTimeMillis());
        audit.setGmtCreate(gmtCreateTime);
        audit.setGmtModified(gmtCreateTime);

        Integer result = (Integer) Execute.execute(Execute.UPDATE_TYPE, AUDIT_MAPPER_ADDRESS + "addAudit", new Object[]{audit});
        return result > 0;
    }

    /**
     * 通过用户id查看是否有已经发出的申请
     *
     * @param userId 用户id
     * @return boolean
     * @author Ding YuXing
     * @date 2021/8/8 10:45
     */
    private boolean findAuditByUserId(Long userId) {
        List<Long> audits = (List<Long>) Execute.execute(Execute.QUERY_TYPE, AUDIT_MAPPER_ADDRESS + "findAuditByUserId", new Object[]{userId});
        return audits.size() == 0;
    }


    /**
     * 通过申请id查看申请详情
     *
     * @param auditId 申请id
     * @return Audit
     * @author Ding YuXing
     * @date 2021/8/8 10:45
     */
    private Audit findAuditByAuditId(Long auditId) {
        List<Audit> audits = (List<Audit>) Execute.execute(Execute.QUERY_TYPE, AUDIT_MAPPER_ADDRESS + "findAuditByAuditId", new Object[]{auditId});
        return audits.get(0);
    }

    /**
     * 通过申请id查看申请详情(应该查询view表)
     *
     * @param auditId 申请id
     * @return com.bluedot.www.core.pojo.VO.ViewAuditInfo
     * @author Ding YuXing
     * @date 2021/10/10 10:45
     */
    private ViewAuditInfo findAuditByAuditIdView(Long auditId) {
        List<ViewAuditInfo> audits = (List<ViewAuditInfo>) Execute.execute(Execute.QUERY_TYPE, AUDIT_MAPPER_ADDRESS + "findAuditByAuditIdView", new Object[]{auditId});
        return audits.get(0);
    }

    /**
     * 审核申请
     * 审核操作前需要首先查询是否其他管理员已经操作过
     * 已经审核过了 这次审核结果作废 返回false。
     * 这里显示的申请
     * 不会显示被删除的用户发出的申请
     * 但是会显示被封禁的用户发出的申请
     * <p>
     * 申请表主键id 跟 用户id 一定是对应的
     * 用户id 被审核的用户id在用户表中一定要存在且一定是普通用户 只有普通用户可以发出申请且被审核
     * user_role表一定存在用户主键userId跟角色表中普通用户对应的主键roleId 对应的记录
     * 如果该用户是由心理咨询师变为普通用户后再次申请成功变为心理咨询师就存在分组信息
     * 如果是第一次成为心理咨询师就不存在分组信息
     * 如果审核结果是通过的话 如果不存在默认分组就新建一个分组信息 "默认分组" 如果存在默认分组 则不新建。
     * <p>
     * 测试要满足的条件
     * 1.申请表中要有申请记录 审核人员编号字段为null 审核结果字段为0 审核描述为null
     * 2.用户表中要有该userId对应的用户信息 用户类别usertype字段为0
     * 3.user_role表要有用户主键userId跟角色表中普通用户对应的主键roleId 对应的记录
     * 4.group表中该用户id 可以存在分组信息
     * 如果该用户是由心理咨询师变为普通用户后再次申请成功变为心理咨询师就存在分组信息
     * 如果是第一次成为心理咨询师就不存在分组信息
     * <p>
     * 审核后的结果：
     * 1.成功：
     * a.申请表中修改申请记录 审核人员编号字段为auditId 审核结果字段改为1 审核描述为auditDes
     * b.用户表中该userId对应的用户信息 用户类别usertype字段改为1
     * c.user_role表中用户主键userId跟角色表中普通用户对应的主键roleId 对应的记录改为
     * 用户主键userId跟角色表中心理咨询师对应的主键roleId
     * d.group表中该用户id 如果不存在默认分组就新建一个分组信息 "默认分组" 如果存在默认分组 则不新建。
     * 上面四个全部正确才返回成功
     * <p>
     * 2.失败：
     * a.申请表中修改申请记录 审核人员编号字段为auditId 审核结果字段改为2 审核描述为auditDes
     * 结束
     *
     * @param id       申请表主键id 这个申请表主键id对应的数据对应的用户id都是没有被删除的
     * @param userId   用户id
     * @param auditId  审核人员编号id
     * @param result   审核结果对应的数字 1通过 2失败
     * @param auditDes 审核备注
     * @return Boolean
     * @author Ding YuXing
     * @date 2021/8/8 10:45
     */
    private Boolean doAudit(Long id, Long userId, Long auditId, Long result, String auditDes) {

        //完成审核操作前需要首先查询是否其他管理员已经操作过
        Integer resultByAuditId = findAuditResultByAuditId(id);
        if (resultByAuditId != 0){
            //已经审核过了
            //这次审核结果作废 返回false。
            return false;
        }

        User user = (User) UserService.execute("findUserByUserId",new Object[]{userId});
        String email = user.getEmail();
        String html = null;

        String idStr = Long.toString(id);
        String auditIdStr = Long.toString(auditId);
        String resultStr = Long.toString(result);

        Object[] objects = new Object[4];

        Map map = new HashMap<String, Object>(1);
        map.put("id", idStr);

        Map map2 = new HashMap<String, Object>(1);
        map2.put("auditId", auditIdStr);

        Map map3 = new HashMap<String, Object>(1);
        map3.put("result", resultStr);

        Map map4 = new HashMap<String, Object>(1);
        map4.put("auditDes", auditDes);

        objects[0] = map;
        objects[1] = map2;
        objects[2] = map3;
        objects[3] = map4;

        //申请表修改记录
        Integer execute = (Integer) Execute.execute(Execute.UPDATE_TYPE, AUDIT_MAPPER_ADDRESS + "doAudit", objects);

        //结果通过
        if (result == 1) {
            Object[] object = new Object[]{userId, result};
            // 通过
            //成功再调用userService 通过用户id切换用户类型
            //同时switchUserByUserId会修改用户角色表
            Boolean switchResult = (Boolean) UserService.execute("switchUserByUserId", object);

            //判断该用户是否有默认分组 如果该用户是由心理咨询师变为普通用户后再次申请成功变为心理咨询师就存在默认分组
            List<Group> groups = (List<Group>) GroupService.execute("listGroups", new Object[]{userId});
            boolean flag = false;
            for (Group group : groups) {
                if (group.getGroupName().equals("默认分组")) {
                    //有默认分组
                    flag = true;
                    break;
                }
            }

            //没有默认分组
            if (!flag) {
                //再加一个默认分组
                Group group = new Group();
                group.setGroupName("默认分组");
                group.setUserId(userId);
                Object[] object1 = new Object[]{group};
                //调用GroupService
                Boolean insertResult = (Boolean) GroupService.execute("insertGroup", object1);
                //申请表修改记录返回1代表成功 并且 通过用户id切换用户类型成功 同时switchUserByUserId会修改用户角色表也要成功
                //再加一个默认分组成功 四个sql全部成功返回真true
                if (execute == 1 && switchResult && insertResult){
                    //全部成功就发邮件
                    try {
                        File file = new File(this.getClass().getResource("/static/apply.html").getPath());
                        html = MailUtil.readHTML(file);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    MailBo mailBo = new MailBo(email, "AuditResults", html, "审核结果","恭喜您，通过心理咨询师申请！",auditDes+" 请再次登录查看");
                    MailUtil.fixThreadSendmail("application.properties", mailBo);

                    return true;
                }else return false;
            }

            //有默认分组
            //申请表修改记录返回1代表成功 并且 通过用户id切换用户类型成功 同时switchUserByUserId会修改用户角色表也要成功
            //三个sql全部成功返回真true
            if (execute == 1 && switchResult){
                //全部成功就发邮件
                try {
                    File file = new File(this.getClass().getResource("/static/apply.html").getPath());
                    html = MailUtil.readHTML(file);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                MailBo mailBo = new MailBo(email, "AuditResults", html, "审核结果","恭喜您，通过心理咨询师申请！",auditDes+" 请再次登录查看吧");
                MailUtil.fixThreadSendmail("application.properties", mailBo);

                return true;
            }else return false;
        }

        //结果不通过
        //发邮件
        try {
            File file = new File(this.getClass().getResource("/static/apply.html").getPath());
            html = MailUtil.readHTML(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        MailBo mailBo = new MailBo(email, "AuditResults", html, "审核结果","很遗憾，您未能通过心理咨询师申请!",auditDes+" 您可以重新申请");
        MailUtil.fixThreadSendmail("application.properties", mailBo);

        return execute == 1;
    }

    /**
     * 获得笔迹特征数量
     * @return java.lang.Integer 笔迹特征的数量
     * @author He Peng
     * @date 2021/9/8 20:56
     */
    private Integer countAudit() {
        List<Integer> tmp = (List<Integer>) Execute.execute(Execute.QUERY_TYPE,
                AUDIT_MAPPER_ADDRESS + "countAudit", null);
        if (tmp != null && tmp.size() > 0) {
            return tmp.get(0);
        }
        return 0;
    }
}
